<template>
  <div class="hello">
    {{ msg }}
    {{ count }}
    {{ user.age }}
    <button @click="addCount">add count</button>
  </div>
</template>

<script lang="ts">
import Vue, { PropType } from 'vue';

interface IUser {
  age: number;
  sex: 'man' | 'woman';
  address: {
    province: 'shandong' | 'beijing';
    company: 'meituan' | 'byteDance';
  }
}

interface Foo { // 作为接口返回的数据的类型接口
  a: string;
  b: string;
}

interface FooEx extends Foo { // 我们拿到接口返回的原始数据处理之后的数据类型，有可能通过原始数据计算得到了新的属性，那么就在这个接口上拓展来体现
  ab: string; // a+b
}

export default Vue.extend({
  // 总结
  /**
   * 1、props：在校验对象中即使使用PropType结合泛型来规定类型，父组件给props传值以及props组件自身通过this.$props.xxx访问属性时仍然没有类型检查与提示
   * 2、data：如何做到在vue2 + ts中对data配置进行比较优雅的类型定义，如下bar与bars，都通过类型断言搭配接口，这样也比较统一、优雅
   *    下面用到初始值为undefined的变量（bar）时，都统一放到一个if判断里即可（ if(this.bar){...} ）
   * 3、methods：里面的方法定义可以当作正常的ts函数，标注返回值，以及函数内部给变量标注类型
   * 4、computed：不知为何，一旦配置计算属性，就会出现类型报错，比如计算属性中使用了this.count，那么上面所有使用this.count的地方都会报错：Vue类型(this)中不存在属性count（纳尼???）
   */
  name: 'HelloWorld',
  props: {
    msg: String,
    user: {
      type: Object as PropType<IUser>,
      required: true,
    }
  },
  data() {
    return {
      count: 0 as number,
      bar: undefined as FooEx | undefined,
      bars: [] as FooEx[],
    }
  },
  methods: {
    addCount(): void {
      const addNumber: number | undefined = 123;
      this.count += addNumber;
      console.log(this.$props.user.age);
      console.log(this.$props.msg);
    },
    getDoubleCount(): number {
      return this.count * 2;
    }
  },
  // computed: {
  //   test() {
  //     return this.count * 2;
  //   }
  // }
});
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
